﻿using FurionApiDemo.Core.Entity;
using FurionApiDemo.Util.Helper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace FurionApiDemo.Web.Core.Filter
{
    public class RequestAuditFilter : IAsyncActionFilter
    {
        private readonly ILogger<RequestAuditFilter> _logger;

        public RequestAuditFilter(ILogger<RequestAuditFilter> logger)
        {
            _logger = logger;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            //============== 这里是执行方法之前获取数据 ====================

            // 获取控制器、路由信息
            var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

            // 获取请求的方法
            var method = actionDescriptor.MethodInfo;

            // 获取 HttpContext 和 HttpRequest 对象
            var httpContext = context.HttpContext;
            var httpRequest = httpContext.Request;

            // 获取客户端 Ipv4 地址
            var remoteIPv4 = httpContext.GetRemoteIpAddressToIPv4();

            // 获取请求的 Url 地址
            var requestUrl = httpRequest.GetRequestUrlAddress();

            // 获取来源 Url 地址
            var refererUrl = httpRequest.GetRefererUrlAddress();

            // 获取请求参数（写入日志，需序列化成字符串后存储）
            var parameters = context.ActionArguments;

            // 获取操作人（必须授权访问才有值）"userId" 为你存储的 claims type，jwt 授权对应的是 payload 中存储的键名
            var userId = httpContext.User?.FindFirstValue("userId");

            // 请求时间
            var requestedTime = DateTimeOffset.Now;


            //============== 这里是执行方法之后获取数据 ====================
            var actionContext = await next();


            // 判断是否请求成功，没有异常就是请求成功
            var isRequestSucceed = actionContext.Exception == null;

            // 这里写入日志~~~~~~~~~~~~~~~~~~~~

            _logger.LogInformation(JsonConvert.SerializeObject(new SysLogVis
            {
                Account = userId,
                Ip = remoteIPv4,
                Location = refererUrl,
                Name = method.Name,
                VisTime = requestedTime,
                VisType = 1,
                Browser = NetHelper.Browser,
                Os = NetHelper.GetOSVersion(),
                Success = isRequestSucceed ? "Y" : "N",
                Message = $"%{userId}请求{requestUrl}，参数{JsonConvert.SerializeObject(parameters)}%"
            }));
        }
    }
}
